#ifndef _BOX_H
#define _BOX_H

#include "vector.h"

class Box
{ 
	protected:
		Vector a, b; //!< End vertices of the box.
	
	public:
		static const double epsilon;

	public:
		Box() {}
		Box(const Vector& u) : a(u), b(u) {}
		Box(const Vector& u,const Vector& v) : a(u), b(v) {}
		Box(const Vector& c,const double& r) : a(c - Vector(r, r, r)), b(c + Vector(r, r, r)) {}
		Box(const Box& x,const Box& y) : a(min(x.a, y.a)), b(max(x.b, y.b)) {}

		~Box() {}

		// Access vertexes
		Vector& operator[] (int);
		Vector operator[] (int) const;

		Vector Center() const { return 0.5 * (a + b); }
		Vector Diagonal() const { return 0.5 * (b - a); }
		double Radius() const { return 0.5 * Norm(b - a); }
		Vector Vertex(int k) const { return Vector((k&1)? b[0] : a[0], (k&2)? b[1] : a[1], (k&4)? b[2] : a[2]); }

		int Intersect(const Box& box) const { return (*this) && box; }

		bool Inside(const Box& box) const { return ((a < box.a) && (b > box.b)); }
		bool Inside(const Vector& u) const { return ((a < u) && (b > u)); }

		friend bool operator&&(const Box&,const Box&);

		double Volume() const;
		double Area() const;
	
};

//! Returns either end vertex of the box.
inline Vector& Box::operator[] (int i) 
{
	if (i==0)
		return a;
	else
		return b;
}

//! Overloaded.
inline Vector Box::operator[] (int i) const 
{
	if (i==0)
		return a;
	else
		return b;
}

//! Compute the volume of a box.
inline double Box::Volume() const
{
	Vector side = b - a;
	return side[0] * side[1] * side[2];
}

//! Compute the surface area of a box.
inline double Box::Area() const
{
	Vector side = b - a;
	return 2.0 * (side[0] * side[1] + side[0] * side[2] + side[1] * side[2]);
}

/*!
\brief Checks if two boxes in space intersect.
*/
inline bool operator&&(const Box& x,const Box& y)
{
	if ((x.a[0] >= y.b[0]) ||
		(x.a[1] >= y.b[1]) ||
		(x.a[2] >= y.b[2]) ||
		(x.b[0] <= y.a[0]) ||
		(x.b[1] <= y.a[1]) ||
		(x.b[2] <= y.a[2]))
		return false;
	else
		return true;
}

#endif // _BOX_H
